#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <cstddef>
#include <cstdint>

using namespace std;

const string base16_enc_tab{"0123456789ABCDEF"};
const vector<char> base16_dec_tab{
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0 - 9
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10 - 19
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20 - 29
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 30 - 39
    -1, -1, -1, -1, -1, -1, -1, -1,         // 40 - 47
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,           // 48 - 57
    -1, -1, -1, -1, -1, -1, -1,             // 58 - 64
    10, 11, 12, 13, 14, 15,                 // 65 - 70

};

string base16Encode(const string &str)
{

    string base16String;

    for (uint8_t c : str)
    {
        uint8_t H = c >> 4 & 0x0f;
        uint8_t L = c & 0x0f;

        base16String += base16_enc_tab[H];
        base16String += base16_enc_tab[L];
    }
    return base16String;
}

string base16Decode(const string &base16Str)
{
    union
    {
        struct
        {
            uint8_t L : 4;
            uint8_t H : 4;
        };
        uint8_t value;
    } HL;

    if (base16Str.size() % 2 != 0)
    {
        return "";
    }
    string str;
    for (int i = 0; i < base16Str.size(); i += 2)
    {
        uint8_t c = 0x00;
        uint8_t ch = base16Str[i];
        uint8_t cl = base16Str[i + 1];
        HL.H = base16_dec_tab[ch];
        HL.L = base16_dec_tab[cl];
        str += HL.value;
    }
    return str;
}

int main(int argc, char const *argv[])
{
    string testString{"测试用于base16的字符串"};

    string base16String = base16Encode(testString);

    cout << "UTF8       :" << testString << endl;
    cout << "base16    :" << base16String << endl;
    cout << "base16Decode:" << base16Decode(base16String) << endl;
    return 0;
}
